#include "stm32f10x.h"    
#include "freertos.h"
#include "task.h"
#include "queue.h"
#include "Delay.h"

#include <string.h>

#include "USART_Config.h"
#include "ESP01s_Control.h"
#include "HC05_Control.h"
#include "LED_Init.h"
#include "Buzzer_Init.h"

#define QUEUE_LENGTH 16	 					// 队列长度
#define ITEM_SIZE sizeof(USART_Message_t)	// 队列项大小
QueueHandle_t xQueue;

void USART_Handler(void);
void vTask_ESP01s_Controller(void *arg);
void vTask_ESP01s_Heartbeat(void *arg);

/*
// √ 1. 心跳保活机制：
		- 实现最基本的每分钟心跳包（0x0002）
		- 使用FreeRTOS的 xTaskCreate + vTaskDelay；
// √ 2. 设备状态转发：
		- 定义LED/蜂鸣器控制结构体（先不实现具体硬件控制）
		- 实现设备状态报文（0x0001）
// √ 3. 服务器消息路由
		- 服务器根据PacketID区分来源（STM32/手机/其他）
// √ 4. STM32硬件控制
		- 初始化LED/蜂鸣器GPIO
		- 将硬件操作封装成函数
// 	 5. 手机客户端转发
		- 在服务器添加客户端管理列表
		- 实现手机连接服务器
		- 服务器实现客户端转发客户端
// 增加ADC传感器，将传感器的内容写到客户端
// 增加服务器日志功能
// 增加服务器配置文件功能
// 增加蓝牙，传向ESP-01
// 将消息改为小火车：结构体+数据两次发送
*/

int main(void){
	Delay_Init();						// 初始化 Delay函数
	
	USART_Pin_Init(&USART1_Cfg);  		// 初始化 USB_TO_TTL
	USART_Pin_Init(&USART2_Cfg);  		// 初始化 ESP01s
//	USART_Pin_Init(&USART3_Cfg);  		// 初始化 HC05
	USART_NVIC_Init(&USART1_Cfg);  		// 初始化 中断源优先级
	USART_NVIC_Init(&USART2_Cfg);  		
	
	LED_Init();
	Buzzer_Init();
	USART_Handler();
//	HC05_Control();						// 开始蓝牙<扫描不到我的设备，放弃了>
	
	xQueue = xQueueCreate(QUEUE_LENGTH,  ITEM_SIZE);

	xTaskCreate(vTask_ESP01s_Controller, "vTask_LED_Controller", configMINIMAL_STACK_SIZE * 4, NULL, 2, NULL);	
	xTaskCreate(vTask_ESP01s_Heartbeat, "vTask_ESP01s_Heartbeat", configMINIMAL_STACK_SIZE * 2, NULL, 1, NULL);	
	vTaskStartScheduler();					// 启动调度器，调试到此处按F11
	
	while(1);								// 程序不应执行到这里
}

// 串口任务
void USART_Handler(void) {
	Delay_ms(2000);
	
    const char *hello_str = 
        "ESP01s Controller COMMANDS:\r\n"
	    "  ESPSTART\r\n"
		"  ESPSEND\r\n"
        "  ESPSTATUS\r\n"
        "  ESPEND\r\n"
        "-----------------------\r\n"
        "Waiting for input...\r\n";

    USART_Message_t msg = {
		.source_id = 2,
		.device_id = DEVICE_USART,
		.len = strlen(hello_str),
	};

    memcpy(msg.data, hello_str, (msg.len < MAX_STR_LEN) ? msg.len : MAX_STR_LEN-1);		// 适合二进制数据
    
    msg.data[MAX_STR_LEN-1] = '\0';  

    USART_printf(&USART1_Cfg, (char*)msg.data);
}

// USART1控制任务
void vTask_ESP01s_Controller(void *arg) {	
	USART_Message_t msg;
	char msg_rev[MAX_STR_LEN] = {0};
	
    while(1) {		
		if(xQueueReceive(xQueue, &msg, 500) == pdPASS){			// 写portMAX_DELAY会被持续阻塞
//			if(msg.source_id == 1 || (msg.source_id == 2 && ESP_state == ESP_state_CONNECT)){
			if(msg.source_id == 1){
				strcpy(msg_rev, (const char*)msg.data);	
				if(strncmp(msg_rev, "ESPSTATUS", 9) == 0){		// 0标识相等
					ESP_Status();  
				}				
				if(strncmp(msg_rev, "ESPSEND", 7) == 0){		// 0标识相等
					ESP_SendPacket();
				}	
				if(strncmp(msg_rev, "ESPSTART", 8) == 0){		// 0标识相等
					ESP_index = 0;
					ESP_state = ESP_state_START;
					ESP_StControl();  
				}	
				if(strncmp(msg_rev, "ESPEND", 6) == 0){			// 0标识相等
					ESP_index = 0;
					ESP_state = ESP_state_END;
					ESP_EdControl();  
				}
				USART_printf(&USART1_Cfg, "USART1 Receive the str: %s \r\n", (msg_rev));	
				memset(msg_rev, sizeof(msg_rev), 0);
			}
			if(msg.source_id == 2){
				size_t copy_len = (msg.len < MAX_STR_LEN-1) ? msg.len : MAX_STR_LEN-1;		// 安全拷贝数据
				memcpy(msg_rev, msg.data, copy_len);
				msg_rev[copy_len] = '\0';  				// 确保字符串终止
				strcpy(msg_rev, (const char*)msg.data);
				
				if(strcmp(msg_rev, "OK\r") == 0 && ESP_state == ESP_state_START){			// 0标识相等
					ESP_StControl();  
				}	
				if(strcmp(msg_rev, "ready\r") == 0 && ESP_state == ESP_state_START){		// 0标识相等
					ESP_index = 3;
					ESP_StControl();  
				}	
				if(strcmp(msg_rev, "OK\r") == 0 && ESP_state == ESP_state_END){			
					ESP_EdControl();  
				}						
				
				USART_printf(&USART1_Cfg, "USART2 Receive the str: %s \r\n", (msg_rev));	// 注意此处输出到屏幕，而非ESP-01
				memset(msg_rev, sizeof(msg_rev), 0);
			}
			if(msg.source_id == 3){
			}
		}
		vTaskDelay(100);
	}
}

void vTask_ESP01s_Heartbeat(void *arg){
	while(1){
//		if(ESP_state == ESP_STATE_TRANSPARENT){
			ESP_SendPacket();
//		}
		vTaskDelay(60000);
	}
}
